<!--
* @author luguoxiang
* @date 2021-09-07
* 开源项目：https://gitee.com/lgx1992/lg-soar 求star！请给我star！请帮我点个star！
-->
<template>
  <div v-onresize.width="onresize" class="lg-grid-c" :style="style">
    <div :class="className" v-bind="$attrs">
      <slot></slot>
    </div>
  </div>
</template>

<script lang="ts" setup>
import { computed, ref, watch, watchEffect } from 'vue';
import { LgGridProps } from '../types';

const emit = defineEmits(['change']);

interface Props extends LgGridProps {
  /**
   * 列宽度
   */
  width?: number;
  /**
   * 间距，数组时第一个是垂直间距，第二个是水平间距
   */
  gap?: number | [number, number];
  /**
   * 是否禁用列宽计算（js动态宫格功能失效，不随窗口父元素宽度变化自动计算宫格宽度）
   */
  disabled?: boolean;
  /**
   * 最少列数
   */
  minColumn?: number;
  /**
   * 最大列数
   */
  maxColumn?: number;
}
const props = withDefaults(defineProps<Props>(), {
  width: 350,
  disabled: false,
  minColumn: 1,
  maxColumn: Infinity,
});
const style = ref({});
// 宫格父元素类名
const className = computed(() => (props.disabled ? '' : 'lg-grid-container'));
// 间距
const gap = computed(() => {
  const { gap } = props;
  if (typeof gap === 'number') {
    return [gap / 2, gap / 2];
  }
  if (Array.isArray(gap)) {
    return [(gap[0] ?? 0) / 2, (gap[1] ?? 0) / 2];
  }
  return [0, 0];
});
// 宫格列宽
const itemWidth = computed(() => gap.value[1] * 2 + props.width);
let parentWidth = 0;
let oldCount = 0;
// 计算每行显示数
function calc() {
  const { minColumn, maxColumn } = props;
  const iw = itemWidth.value;
  let count = Math.floor(parentWidth / iw);
  if (count < minColumn) {
    count = minColumn;
  }
  if (count > maxColumn) {
    count = maxColumn;
  }
  // 是否发生了变化
  if (oldCount === count) {
    return;
  }
  oldCount = count;
  if (parentWidth < iw) {
    style.value['--lg-grid-width'] = `${iw}px`;
  } else {
    style.value['--lg-grid-width'] = `${100 / count}%`;
  }
  emit('change', count);
}
// 监听宽度变化
function onresize(el: Element) {
  if (Math.abs(parentWidth - el.clientWidth) > 20) {
    parentWidth = el.clientWidth;
    calc();
  }
}
// 监听
watch(() => itemWidth.value, calc);
watch(() => props.minColumn, calc);
watch(() => props.maxColumn, calc);
// 监听边距
watchEffect(() => {
  const g = gap.value;
  style.value['--lg-grid-padding'] = `${g[0]}px ${g[1]}px`;
  style.value['--lg-grid-margin'] = `-${g[0]}px -${g[1]}px`;
});
</script>
<script lang="ts">
export default {
  name: 'LgGrid',
};
</script>

<style lang="less" scoped>
.lg-grid-c {
  overflow: hidden;
}
.lg-grid-container {
  --lg-grid-min: 1;
  --lg-grid-max: 1;
  display: flex;
  flex-wrap: wrap;
  align-items: stretch;
  margin: var(--lg-grid-margin);
  > :nth-child(n) {
    padding: var(--lg-grid-padding);
    min-width: calc(var(--lg-grid-width) * var(--lg-grid-min));
    max-width: calc(var(--lg-grid-width) * var(--lg-grid-max));
    flex: 1;
    box-sizing: border-box;
  }
}
</style>
